package com.youlin.controller;

import com.youlin.dto.BaseResDto;
import com.youlin.dto.Status;
import com.youlin.untils.UnIntercept;
import org.apache.commons.lang.StringUtils;
import org.quartz.*;
import org.quartz.impl.calendar.HolidayCalendar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;

@RestController
@RequestMapping("/quartzManager")
public class QuartzManager {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @UnIntercept
    @GetMapping("/addJob")
    public BaseResDto addJob(String jobName, String jobGroupName, String triggerName,
                             String triggerGroupName, String jobClassName, String cron) {
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();

            JobDetail jobDetail= JobBuilder
                    .newJob((Class<? extends Job>) Class.forName(jobClassName))
                    .withIdentity(jobName, jobGroupName)
                    .storeDurably()
                    .build();

            CronTrigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .build();

            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) sched.start();

            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @UnIntercept
    @GetMapping("/modifyHolidayCalendar")
    public BaseResDto modifyHolidayCalendar(String calName, String addExcludedDate, String removeExcludedDate) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            HolidayCalendar holidayCalendar = (HolidayCalendar) scheduler.getCalendar(calName);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if (StringUtils.isNotBlank(addExcludedDate))
                holidayCalendar.addExcludedDate(sdf.parse(addExcludedDate));
            if (StringUtils.isNotBlank(removeExcludedDate))
                holidayCalendar.removeExcludedDate(sdf.parse(removeExcludedDate));
            scheduler.addCalendar(calName, holidayCalendar, true, true);
            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @UnIntercept
    @GetMapping("/modifyJobTime")
    public BaseResDto modifyJobTime(String triggerName, String triggerGroupName, String cron, String calName) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();

            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) return new BaseResDto(Status.PARAMETERERROR);
//            if (trigger.getCronExpression().equalsIgnoreCase(cron))
//                return new BaseResDto(Status.PARAMETERERROR);

            calName = StringUtils.isBlank(calName) ? null : calName;
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
                    .cronSchedule(cron)
                    .withMisfireHandlingInstructionDoNothing();
            trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(cronScheduleBuilder)
                    .modifiedByCalendar(calName)
                    .build();
            scheduler.rescheduleJob(triggerKey, trigger);
            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public BaseResDto removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();

            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

            sched.pauseTrigger(triggerKey); // 停止触发器
            sched.unscheduleJob(triggerKey); // 移除触发器
            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName)); // 删除任务

            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @UnIntercept
    @GetMapping("/startJobs")
    public BaseResDto startJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            if (scheduler.isInStandbyMode()) scheduler.start();

            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @UnIntercept
    @GetMapping("/standbyJobs")
    public BaseResDto standbyJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            if (scheduler.isShutdown()) return new BaseResDto(Status.ERROR);
            scheduler.standby();

            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @UnIntercept
    @GetMapping("/shutdownJobs")
    public BaseResDto shutdownJobs() {
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();
            if (! sched.isShutdown()) sched.shutdown();

            return new BaseResDto(Status.SUCCESS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
